﻿using System;
using System.Collections.Generic;
using System.Linq;
using Autodesk.Revit.DB;
using Autodesk.Revit.DB.Electrical;
using Autodesk.Revit.DB.Mechanical;
using Autodesk.Revit.DB.Plumbing;
using Autodesk.Revit.UI;
using YArchitech.Revit;
using HYCodeBase.TopologySuite;
using HYRevitCode.RevitTopologySuite;
using YJKRGeometry;

namespace AdjustInstallationHeight
{
	internal class GroupCalculation
	{
		public static bool JudgeIsNaturalNumber(string strNumber)
		{
			int num = 0;
			return int.TryParse(strNumber, out num) && Geometry.Lessthan_Or_Equal(0.0, (double)num);
		}

		public static List<PrepareMoveStructure> PrepareMoveData(UIDocument uiDoc, ElementNeedMoveAnalyzer useElementAnalyzer)
		{
			List<PrepareMoveStructure> list = new List<PrepareMoveStructure>();
			new List<List<Element>>();
			PrepareMoveStructure prepareMoveStructure = new PrepareMoveStructure();
			foreach (KeyValuePair<BeamAndFloorInfo, List<Element>> data in GroupCalculation.MakeGroup(uiDoc, useElementAnalyzer))
			{
				prepareMoveStructure = new PrepareMoveStructure();
				foreach (List<Element> item in GroupCalculation.GetGroupOfIntersect(data))
				{
					prepareMoveStructure.LstPrepareMoveElement.Add(item);
				}
				prepareMoveStructure.BeamAndFloorInfo = data.Key;
				list.Add(prepareMoveStructure);
			}
			return list;
		}

		private static List<List<Element>> GetGroupOfIntersect(KeyValuePair<BeamAndFloorInfo, List<Element>> data)
		{
			List<List<Element>> list = new List<List<Element>>();
			List<Element> value = data.Value;
			List<Element> list2 = new List<Element>();
			new List<Element>();
			while (value.Count > 0)
			{
				list2 = new List<Element>();
				list2.Add(value[0]);
				value.Remove(value[0]);
				for (int i = 0; i < list2.Count; i++)
				{
					for (int j = 0; j < value.Count; j++)
					{
						if (GroupCalculation.JudgeIntersect(list2[i], value[j], data.Key.m_face) && !list2.Contains(value[j]))
						{
							list2.Add(value[j]);
							value.Remove(value[j]);
						}
					}
				}
				list2 = (from k in list2
				orderby (k.Location as LocationCurve).Curve.GetEndPoint(0).Z descending
				select k).ToList<Element>();
				list.Add(list2);
			}
			return list;
		}

		private static List<KeyValuePair<BeamAndFloorInfo, List<Element>>> MakeGroup(UIDocument uiDoc, ElementNeedMoveAnalyzer useElementAnalyzer)
		{
			List<KeyValuePair<BeamAndFloorInfo, List<Element>>> list = new List<KeyValuePair<BeamAndFloorInfo, List<Element>>>();
			BeamAndFloorSearcher beamAndFloorSearcher = new BeamAndFloorSearcher(uiDoc.Document);
			foreach (Element element in useElementAnalyzer.LstElement)
			{
				MEPCurve mepcurve = element as MEPCurve;
				Level referenceLevel = mepcurve.ReferenceLevel;
				double z = (mepcurve.Location as LocationCurve).Curve.GetEndPoint(0).Z;
				foreach (BeamAndFloorStructure beamAndFloorStructure in beamAndFloorSearcher.LstBeam)
				{
					if (Geometry.LessThan(z, beamAndFloorStructure.m_dLevel))
					{
						foreach (BeamAndFloorInfo face in beamAndFloorStructure.m_lstFaceInfo)
						{
							GroupCalculation.IsAddToDataList(list, element, face);
						}
					}
				}
				foreach (BeamAndFloorStructure beamAndFloorStructure2 in beamAndFloorSearcher.LstFloor)
				{
					if (Geometry.LessThan(z, beamAndFloorStructure2.m_dLevel))
					{
						foreach (BeamAndFloorInfo face2 in beamAndFloorStructure2.m_lstFaceInfo)
						{
							GroupCalculation.IsAddToDataList(list, element, face2);
						}
					}
				}
			}
			return list;
		}

		private static void IsAddToDataList(List<KeyValuePair<BeamAndFloorInfo, List<Element>>> lstData, Element itemElem, BeamAndFloorInfo face)
		{
			Curve curve = (itemElem.Location as LocationCurve).Curve;
			if (GroupCalculation.CurveProjectToPlanarFace(curve, face.m_face as PlanarFace, out curve))
			{
				bool flag = false;
				foreach (KeyValuePair<BeamAndFloorInfo, List<Element>> keyValuePair in lstData)
				{
					if (keyValuePair.Key == face)
					{
						flag = true;
						keyValuePair.Value.Add(itemElem);
					}
				}
				if (!flag)
				{
					lstData.Add(new KeyValuePair<BeamAndFloorInfo, List<Element>>(face, new List<Element>
					{
						itemElem
					}));
				}
			}
		}

		private static bool JudgeIntersect(Element elemOne, Element elemTwo, Face face)
		{
			Curve curve = (elemOne.Location as LocationCurve).Curve;
			Curve curve2 = (elemTwo.Location as LocationCurve).Curve;
			Curve curve3 = null;
			Curve curve4 = null;
			GroupCalculation.CurveProjectToPlanarFace(curve, face as PlanarFace, out curve3);
			GroupCalculation.CurveProjectToPlanarFace(curve2, face as PlanarFace, out curve4);
			if (curve3 == null && curve4 == null)
			{
				return false;
			}
			RevitPolygonDataBean revitPolygonDataBean = GroupCalculation.CreatePolygen(elemOne, curve3 as Line);
			RevitPolygonDataBean revitPolygonDataBean2 = GroupCalculation.CreatePolygen(elemOne, curve4 as Line);
			if (revitPolygonDataBean == null || revitPolygonDataBean2 == null)
			{
				return false;
			}
			TopologyRelateKindEnum topologyRelateKindEnum;
			new RevitPolygonRelateOperater().TryGetPolygonRelate(revitPolygonDataBean, revitPolygonDataBean2, out topologyRelateKindEnum);
			return topologyRelateKindEnum != TopologyRelateKindEnum.Disjoint;
		}

		private static RevitPolygonDataBean CreatePolygen(Element element, Line lineCenter)
		{
			double num = 0.0;
			int integerValue = element.Category.Id.IntegerValue;
			if (integerValue != -2008130)
			{
				if (integerValue != -2008044)
				{
					if (integerValue != -2008000)
					{
						return null;
					}
					GroupCalculation.GetElementHeight(element as Duct, out num);
				}
				else
				{
					GroupCalculation.GetElementHeight(element as Pipe, out num);
				}
			}
			else
			{
				GroupCalculation.GetElementHeight(element as CableTray, out num);
			}
			XYZ endPoint = lineCenter.GetEndPoint(0);
			XYZ endPoint2 = lineCenter.GetEndPoint(1);
			XYZ xyz = lineCenter.Direction.CrossProduct(XYZ.BasisZ);
			XYZ xyz2 = endPoint + xyz * num / 2.0;
			XYZ xyz3 = endPoint2 + xyz * num / 2.0;
			XYZ xyz4 = endPoint2 + xyz * (-num / 2.0);
			XYZ xyz5 = endPoint + xyz * (-num / 2.0);
			Line item = Line.CreateBound(xyz2, xyz3);
			Line item2 = Line.CreateBound(xyz3, xyz4);
			Line item3 = Line.CreateBound(xyz4, xyz5);
			Line item4 = Line.CreateBound(xyz5, xyz2);
			return new RevitPolygonDataBean(CurveLoop.Create(new List<Curve>(4)
			{
				item,
				item2,
				item3,
				item4
			}), null);
		}

		private static bool GetElementHeight(Duct duct, out double dWidth)
		{
			Parameter parameter = duct.GetParameter(BuiltInParameter.RBS_CURVE_WIDTH_PARAM);
			if (parameter != null)
			{
				dWidth = parameter.AsDouble();
				return true;
			}
			dWidth = 0.0;
			return false;
		}

		private static bool GetElementHeight(Pipe pipe, out double dWidth)
		{
			Parameter parameter = pipe.GetParameter(BuiltInParameter.RBS_PIPE_DIAMETER_PARAM);
			if (parameter != null)
			{
				dWidth = parameter.AsDouble();
				return true;
			}
			dWidth = 0.0;
			return false;
		}

		private static bool GetElementHeight(CableTray cable, out double dWidth)
		{
			Parameter parameter = cable.GetParameter(BuiltInParameter.RBS_CABLETRAY_WIDTH_PARAM);
			if (parameter != null)
			{
				dWidth = parameter.AsDouble();
				return true;
			}
			dWidth = 0.0;
			return false;
		}

		public static bool CurveProjectToPlanarFace(Curve inputCurve, PlanarFace inputPlanarFace, out Curve projectCurve)
		{
			projectCurve = null;
			if (null == inputCurve || null == inputPlanarFace || !inputCurve.IsBound)
			{
				return false;
			}
			List<XYZ> list = new List<XYZ>();
			List<XYZ> list2 = new List<XYZ>();
			double num = 0.0;
			while (Geometry.Lessthan_Or_Equal(num, 1.0))
			{
				list2.Add(inputCurve.Evaluate(num, true));
				num += 0.001;
			}
			bool flag = false;
			foreach (XYZ xyz in list2)
			{
				flag = false;
				IntersectionResult intersectionResult = null;
				intersectionResult = inputPlanarFace.Project(xyz);
				if (intersectionResult != null && intersectionResult.XYZPoint != null)
				{
					using (List<XYZ>.Enumerator enumerator2 = list.GetEnumerator())
					{
						while (enumerator2.MoveNext())
						{
							if (enumerator2.Current.IsAlmostEqualTo(intersectionResult.XYZPoint))
							{
								flag = true;
								break;
							}
						}
					}
					if (!flag)
					{
						list.Add(intersectionResult.XYZPoint);
					}
				}
			}
			if (list.Count < 2)
			{
				return false;
			}
			if (inputCurve is Arc && list.Count > 2)
			{
				try
				{
					projectCurve = Arc.Create(list[0], list[list.Count - 1], list[list.Count / 2]);
					goto IL_16A;
				}
				catch (Exception)
				{
					return false;
				}
			}
			try
			{
				projectCurve = Line.CreateBound(list[0], list[list.Count - 1]);
			}
			catch (Exception)
			{
				return false;
			}
			IL_16A:
			return null != projectCurve;
		}
	}
}
